﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using mfe.bll;
using System.IO;
using System.Collections.Specialized;

namespace mfe_proj.Forms
{
    public delegate void ItemFormEventHandler(object sender, ItemFormEventArgs e);

    public partial class ItemForm : Form
    {
        /// TODO: Combine these two events?
        public event ItemFormEventHandler ItemAdded;
        public event ItemFormEventHandler ItemUpdated;
        public event ItemFormEventHandler ItemChanged;

        public string ItemGuidID;
        public Item item = null;
        public BaseDetailForm detailForm = null;
        List<Photo> TempPhotoCollections;
        List<ItemTag> TempTagCollections;
        bool _IsNew = true;
        public bool IsNew { get { return _IsNew; } set { _IsNew = value; } }

        public ItemForm()
        {
            InitializeComponent();
        }

        void LoadData()
        {
            foreach (Enums.ContentType type in Enum.GetValues(typeof(Enums.ContentType)))
                cbType.Items.Add(type);

            if (ItemGuidID == null || ItemGuidID == string.Empty) return;

            item = new Item(ItemGuidID);
            txtTitle.Text = item.Title;
            txtContent.DocumentText = item.Content;
            txtAuthor.Text = item.Author;
            txtEnteredBy.Text = item.EnteredBy;
            txtSource.Text = item.Source;
            cbType.SelectedItem = (Enums.ContentType)item.ContentType;

            if (cbType.SelectedIndex != -1 &&
                cbType.SelectedIndex != cbType.Items.Count - 1)
                cbType.Enabled = false;

            txtDateCreated.Text = item.CreateDate.ToString();
            txtDateModified.Text = item.ModifiedDate.ToString();

            cbShowInNav.Checked = item.ShowInNav;
            cbSearchable.Checked = item.Searchable;

            cbPrintable.Checked = item.Printable;
            cbEditable.Checked = item.Editable;
            cbIsCore.Checked = item.IsCore;
            cbShowPhotos.Checked = item.ShowPhoto;
            if ((Enums.DefaultPhotoPos)item.DefaultPhotoPos == Enums.DefaultPhotoPos.Left)
                rbLeft.Checked = true;
            else if ((Enums.DefaultPhotoPos)item.DefaultPhotoPos == Enums.DefaultPhotoPos.Right)
                rbRight.Checked = true;
            else if ((Enums.DefaultPhotoPos)item.DefaultPhotoPos == Enums.DefaultPhotoPos.Top)
                rbTop.Checked = true;
            else if ((Enums.DefaultPhotoPos)item.DefaultPhotoPos == Enums.DefaultPhotoPos.Bottom)
                rbBottom.Checked = true;

            //load the existing taggings
            StringCollection condtions = new StringCollection();
            condtions.Add("ItemGuidID='" + ItemGuidID + "'");
            List<ItemTag> tags = ItemTag.ItemTagCollection(null, condtions);
            foreach (ItemTag tag in tags)
                lbTagging.Items.Add(tag);
        }

        StringBuilder ValidateData()
        {
            StringBuilder sb = new StringBuilder();
            if (txtTitle.Text.Trim().Length == 0)
                sb.AppendLine("Please enter the title.");
            if (txtContent.BodyHtml == null || txtContent.BodyHtml.Trim().Length == 0)
                sb.AppendLine("Please enter the content.");
            if (cbType.SelectedIndex == -1)
                sb.AppendLine("Please select a type.");

            return sb;
        }

        bool SaveData()
        {
            StringBuilder sb = ValidateData();
            if (detailForm != null)
                sb.AppendLine(detailForm.ValidateData());

            ///TODO: an empty stringbuider ended up with {} as its content somehow, hence the check for length of 2. probably should fix this later.
            if (sb.ToString().Length > 2)
            {
                ///TODO: should probably write a customize MessageBox to make it show in the center relative to the parent window. 
                ///currently it's showing always in the center of the desktop.
                MessageBox.Show(this, sb.ToString(), "Error saving", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return false;
            }
            

            bool retval = false;
            try
            {
                if (item == null)
                {
                    item = new Item();
                    item.CreateDate = DateTime.Now;
                }
                if (ItemGuidID == null || ItemGuidID == string.Empty)
                    item.ItemGuidID = Guid.NewGuid().ToString();
                item.Title = txtTitle.Text.Trim();
                item.Content = txtContent.BodyHtml.Trim();
                item.ContentType = (int)Enum.Parse(typeof(Enums.ContentType), cbType.SelectedItem.ToString());
                item.Author = txtAuthor.Text.Trim();
                item.EnteredBy = txtEnteredBy.Text.Trim();
                item.Source = txtSource.Text.Trim();
                item.ShowInNav = cbShowInNav.Checked;
                item.Searchable = cbSearchable.Checked;
                item.Printable = cbPrintable.Checked;
                item.Editable = cbEditable.Checked;
                item.IsCore = cbIsCore.Checked;
                item.ShowPhoto = cbShowPhotos.Checked;
                if (rbLeft.Checked)
                    item.DefaultPhotoPos = (int)Enums.DefaultPhotoPos.Left;
                else if (rbRight.Checked)
                    item.DefaultPhotoPos = (int)Enums.DefaultPhotoPos.Right;
                else if (rbTop.Checked)
                    item.DefaultPhotoPos = (int)Enums.DefaultPhotoPos.Top;
                else if (rbBottom.Checked)
                    item.DefaultPhotoPos = (int)Enums.DefaultPhotoPos.Bottom;
                else
                    item.DefaultPhotoPos = (int)Enums.DefaultPhotoPos.Left;

                if (ItemGuidID == null || ItemGuidID == string.Empty)
                {
                    retval = item.Save();
                }
                else
                {
                    retval = item.Update();
                    if (ItemUpdated != null) ItemUpdated(this, new ItemFormEventArgs(item.Title, item.ItemGuidID));
                }

                //raise event
                //if (ItemModified != null)
                //    ItemModified(this, new ItemFormEventArgs((ItemGuidID == null || ItemGuidID == string.Empty), item.Title, item.ItemGuidID));

                //save TempPhotoHolder
                if (TempPhotoCollections != null)
                {
                    foreach (Photo photo in TempPhotoCollections)
                    {
                        photo.ItemGuidID = item.ItemGuidID;
                        photo.Save();
                    }
                }

                //Save TempTagCollections
                if (TempTagCollections != null)
                {
                    foreach (ItemTag tag in TempTagCollections)
                    {
                        tag.ItemGuidID = item.ItemGuidID;
                        tag.Save();
                    }
                }

                //Save 
                if (acRelated.TempRelatedItems != null)
                {
                    foreach (ItemRelated relatedItem in acRelated.TempRelatedItems)
                    {
                        relatedItem.ItemGuidID = item.ItemGuidID;
                        relatedItem.Save();
                    }
                }

                //save the detail form
                if (detailForm != null)
                    detailForm.SaveData(item.ItemGuidID);

                //raise ItemChanged event
                if (ItemChanged != null) ItemChanged(this, new ItemFormEventArgs(item.Title, item.ItemGuidID));
            }
            catch (Exception ex)
            {
                mfe.lib.Logger.Log(ex);
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return retval;
        }

        void SetText()
        {
            Text = string.Concat(_IsNew ? "Add " : "Edit ", cbType.SelectedIndex > -1 ? ((Enums.ContentType)cbType.SelectedItem).ToString() : string.Empty);
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            if (SaveData())
                Close();
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //MessageBox.Show(tabControl1.SelectedTab.Text);
        }

        private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
        {
            if (cbType.SelectedIndex < 0)
                tabControl1.SelectedIndex = 0;
        }

        private void ItemForm_Load(object sender, EventArgs e)
        {
            acRelated.ItemGuidID = ItemGuidID;
            SetText();
            LoadData();

            if (ItemGuidID != null && ItemGuidID != string.Empty)
                LoadPhoto();
        }

        private void cbType_SelectedIndexChanged(object sender, EventArgs e)
        {
            detailForm = null;
            SetText();
            panelItemDetail.Controls.Clear();
            Enums.ContentType type = (Enums.ContentType)Enum.Parse(typeof(Enums.ContentType), cbType.SelectedItem.ToString());
            switch (type)
            {
                case Enums.ContentType.Author:
                case Enums.ContentType.Detective:
                    Forms.PersonForm authorForm = new PersonForm();
                    authorForm.ItemGuidID = ItemGuidID;
                    authorForm.LoadData();
                    authorForm.DockablePanel.Parent = panelItemDetail;
                    detailForm = authorForm;
                    break;
                case Enums.ContentType.Book:
                    Forms.BookForm bookForm = new BookForm();
                    bookForm.ItemGuidID = ItemGuidID;
                    bookForm.LoadData();
                    bookForm.DockablePanel.Parent = panelItemDetail;
                    detailForm = bookForm;
                    break;
                case Enums.ContentType.Website:
                    Forms.WebsiteForm websiteForm = new WebsiteForm();
                    websiteForm.ItemGuidID = ItemGuidID;
                    websiteForm.DockablePanel.Parent = panelItemDetail;
                    detailForm = websiteForm;
                    break;
                case Enums.ContentType.Magazine:
                    Forms.MagazineForm magForm = new MagazineForm();
                    magForm.ItemGuidID = ItemGuidID;
                    magForm.LoadData();
                    magForm.DockablePanel.Parent = panelItemDetail;
                    detailForm = magForm;
                    break;
                case Enums.ContentType.Essay:
                    Forms.EssayForm essayForm = new EssayForm();
                    essayForm.ItemGuidID = ItemGuidID;
                    essayForm.LoadData();
                    essayForm.DockablePanel.Parent = panelItemDetail;
                    detailForm = essayForm;
                    break;
                case Enums.ContentType.Movie:
                    Forms.MovieForm movieForm = new MovieForm();
                    movieForm.ItemGuidID = ItemGuidID;
                    movieForm.LoadData();
                    movieForm.DockablePanel.Parent = panelItemDetail;
                    detailForm = movieForm;
                    break;
                default:
                    detailForm = null;
                    panelItemDetail.Controls.Clear();
                    break;
            }
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            AddTagging();
        }

        private void AddTagging()
        {
            ItemTag tag = new ItemTag();
            tag.ItemTagGuidID = Guid.NewGuid().ToString();
            tag.TagName = txtTagging.Text.Trim();
            //if this is an edit, then ItemGuidID already exist, 
            //if so, add the tag directly to database.
            //otherwise, store the tag in a list, save to database when user clicks OK.
            if (ItemGuidID != null && ItemGuidID != string.Empty)
            {
                tag.ItemGuidID = ItemGuidID;
                tag.Save();
            }
            else
            {
                if (TempTagCollections == null) TempTagCollections = new List<ItemTag>();
                TempTagCollections.Add(tag);
            }

            //clear the text box
            txtTagging.Text = string.Empty;

            //add the tag to the listbox
            lbTagging.Items.Add(tag);
        }

        void LoadPhoto()
        {
            StringCollection fields = new StringCollection();
            StringCollection conditions = new StringCollection();
            fields.Add("PhotoGuidID");
            fields.Add("Title");
            fields.Add("Caption");
            fields.Add("Thumbnail");
            conditions.Add(string.Concat("ItemGuidID='", ItemGuidID, "'"));
            List<Photo> photos = Photo.PhotoCollection(fields, conditions);

            if (photos.Count == 0) return;
            int i = 0;
            foreach (Photo photo in photos)
            {
                using (MemoryStream ms = new MemoryStream(photo.Thumbnail))
                {
                    imageList1.Images.Add(Image.FromStream(ms));
                    ListViewItem lvi = new ListViewItem(photo.Title);
                    lvi.ImageIndex = i++;
                    lvi.Tag = photo.PhotoGuidID;
                    listView1.Items.Add(lvi);
                }
            }
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            ItemTag.Delete(((ItemTag)lbTagging.SelectedItem).ItemTagGuidID);
            lbTagging.Items.RemoveAt(lbTagging.SelectedIndex);
        }

        private void btnRemoveAll_Click(object sender, EventArgs e)
        {
            ItemTag.DeleteItemTags(ItemGuidID);
            lbTagging.Items.Clear();
        }

        private void btnAddPhoto_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    FileInfo info = new FileInfo(openFileDialog1.FileName);
                    byte[] data = new byte[info.Length];
                    byte[] thumbnail;
                    FileStream imagestream = info.OpenRead();
                    imagestream.Read(data, 0, data.Length);
                    Image tempImg = Image.FromStream(imagestream);
                    if (tempImg.Width <= 200)
                        thumbnail = data;
                    else
                        thumbnail = mfe.lib.Imaging.ThumbnailImage(imagestream, 200);
                    imagestream.Close();
                    imagestream.Dispose();
                    Photo photo = new Photo();
                    photo.PhotoGuidID = Guid.NewGuid().ToString();
                    photo.Data = data;
                    photo.Thumbnail = thumbnail;
                    photo.Title = info.Name;

                    if (ItemGuidID != null && ItemGuidID != string.Empty)
                    {
                        //this is an edit, so go ahead and save the photo to database
                        photo.ItemGuidID = ItemGuidID;
                        photo.Save();
                    }
                    else
                    {
                        //this is an insert, no ItemGuidID exist yet, save this photo in a list
                        if (TempPhotoCollections == null) TempPhotoCollections = new List<Photo>();
                        TempPhotoCollections.Add(photo);
                    }

                    //add the photo to the listview
                    using (MemoryStream ms = new MemoryStream(photo.Thumbnail))
                    {
                        imageList1.Images.Add(Image.FromStream(ms));
                        ListViewItem lvi = new ListViewItem(photo.Title);
                        lvi.ImageIndex = imageList1.Images.Count - 1;
                        lvi.Tag = photo.PhotoGuidID;
                        listView1.Items.Add(lvi);
                    }
                }
                catch (Exception ex)
                {
                    mfe.lib.Logger.Log(ex);
                }
            }
        }

        private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
            //update the photo title
            if (e.Label != null & e.Label != listView1.SelectedItems[0].Text)
                Photo.UpdatePhotoTitle(listView1.SelectedItems[0].Tag.ToString(), e.Label);
        }

        private void listView1_DoubleClick(object sender, EventArgs e)
        {
            if (listView1.SelectedIndices.Count <= 0) return;

            PhotoViewerForm pvForm = new PhotoViewerForm();
            pvForm.TitleUpdated += new PhotoInfoFormEventHandler(pvForm_TitleUpdated);
            pvForm.PhotoGuidID = listView1.SelectedItems[0].Tag.ToString();
            pvForm.ShowDialog();
        }

        void pvForm_TitleUpdated(object sender, PhotoInfoFormEventArgs e)
        {
            listView1.SelectedItems[0].Text = e.Title;
        }

        private void btnDeletePhoto_Click(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count <= 0) return;
            //MessageBox.Show(listView1.SelectedItems[0].Tag.ToString());
            if (Photo.Delete(listView1.SelectedItems[0].Tag.ToString()))
                //remove photo from listview
                listView1.SelectedItems[0].Remove();
        }

        private void btnEditInfo_Click(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count <= 0) return;

            PhotoInfoForm infoForm = new PhotoInfoForm();
            infoForm.TitleUpdated += new PhotoInfoFormEventHandler(pvForm_TitleUpdated);
            infoForm.PhotoGuidID = listView1.SelectedItems[0].Tag.ToString();
            infoForm.ShowDialog();
        }
    }

    public class ItemFormEventArgs : EventArgs
    {
        string _Title, _ItemGuidID;
        public string Title { get { return _Title; } set { _Title = value; } }
        public string ItemGuidID { get { return _ItemGuidID; } set { _ItemGuidID = value; } }
        public ItemFormEventArgs() { }
        public ItemFormEventArgs(string title, string itemGuidID)
        {
            Title = title;
            ItemGuidID = itemGuidID;
        }
    }
}
